package com.fan.cachewebview.core

import android.content.Context
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import com.fan.cachewebview.bean.CacheRequest
import com.fan.cachewebview.core.interceptor.ResourceInterceptor
import com.fan.cachewebview.pool.CacheWebView
import com.fan.cachewebview.utils.AppUtils

/**
 * @description $
 * @date: 2022/2/23 15:30
 * @author: fan
 */
class WebResourceCacheImpl internal constructor(context: Context?, webView: CacheWebView) :
    WebResourceCacheApi {
    private var mCacheMode: CacheMode? = null
    private var mCacheConfig: CacheConfig? = null
    private var mLocalCache: LocalCacheApi? = null
    private var mContext: Context?
    private lateinit var mWebView: CacheWebView


    override fun getResource(
        request: WebResourceRequest,
        webViewCacheMode: Int,
        userAgent: String
    ): WebResourceResponse? {

        check(!(mCacheMode === CacheMode.NO_CACHE)) { "an error occurred." }

        // WebView 加载的资源链接
        val url = request.url.toString()
        // 资源扩展名
        val extension: String? = AppUtils.getFileExtensionFromUrl(url)
        // 资源类型
        val mimeType: String? = AppUtils.getMimeTypeFromExtension(extension)

        // 初始化请求带入缓存处理
        val cacheRequest = CacheRequest()
        cacheRequest.url = url
        cacheRequest.mime = mimeType
        cacheRequest.isCacheMode = (mCacheMode === CacheMode.CACHE)
        cacheRequest.setmUserAgent(userAgent)
        cacheRequest.setmWebViewCacheMode(webViewCacheMode)
        // 获取请求中的Headers
        val headers = request.requestHeaders
        cacheRequest.setmHeaders(headers)

        return getLocalCache().get(cacheRequest)
    }

    override fun setCacheMode(mode: CacheMode, config: CacheConfig?) {
        mCacheMode = mode
        mCacheConfig = config
    }

    override fun addResourceInterceptor(interceptor: ResourceInterceptor) {
        getLocalCache().addResourceInterceptor(interceptor)
    }

    @Synchronized
    private fun getLocalCache(): LocalCacheApi {
        if (mLocalCache == null) {
            mLocalCache = LocalCacheImpl(mContext, getCacheConfig())
        }
        return mLocalCache!!
    }

    private fun getCacheConfig(): CacheConfig {
        return if (mCacheConfig != null) mCacheConfig!! else generateDefaultCacheConfig()
    }

    private fun generateDefaultCacheConfig(): CacheConfig {
        return if (mContext != null){
            CacheConfig.Builder(mContext!!).build()
        } else {
            CacheConfig.Builder(mWebView.context).build()
        }
    }

    override fun destroy() {
        if (mLocalCache != null) {
            mLocalCache?.destroy()
        }
        // help gc
        mCacheConfig = null
        mLocalCache = null
    }

    init {
        mContext = context
        mWebView = webView
    }
}